package com.ecreditpal.audio.netty.message;

import com.ecreditpal.audio.util.BaseUtil;
import com.google.protobuf.MessageLite;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @author lifeng
 * @version 1.0 on 2018/7/12.
 */
@Slf4j
public class CustomProtobufDecoder extends ByteToMessageDecoder {
    private MessageLite messageLite;

    public CustomProtobufDecoder(MessageLite messageLite) {
        this.messageLite = messageLite;
    }
    /**
     * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
     * {@link ByteBuf} has nothing to read when return from this method or till nothing was read from the input
     * {@link ByteBuf}.
     *
     * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
     * @param in  the {@link ByteBuf} from which to read data
     * @param out the {@link List} to which decoded messages should be added
     * @throws Exception is thrown if an error occurs
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        while (in.readableBytes() >= 4) { // 如果可读长度小于包头长度，退出。
            in.markReaderIndex();

            byte[] head = new byte[4];
            for (int i = 0; i < 4; i++) {
                head[i] = in.readByte();
                log.debug("byte : {}",BaseUtil.byteToHex(head[i]));
            }

            int length = BaseUtil.bytes2IntReverse(head,0,3);
            log.debug("message data length : {}",length);

            if (length == 0){
                log.debug("heart beat message receive");
                out.add(new Object());
                return;
            }

            // 如果可读长度小于body长度，恢复读指针，退出。
            if (in.readableBytes() < length) {
                log.debug("readableBytes:{} < length:{},return",in.readableBytes(),length);
                in.resetReaderIndex();
                return;
            }

            log.info("read all the bytes :{}",length);
            // 读取body
            ByteBuf bodyByteBuf = in.readBytes(length);

            byte[] array;
            int offset;

            int readableLen= bodyByteBuf.readableBytes();
            if (bodyByteBuf.hasArray()) {
                array = bodyByteBuf.array();
                offset = bodyByteBuf.arrayOffset() + bodyByteBuf.readerIndex();
            } else {
                array = new byte[readableLen];
                bodyByteBuf.getBytes(bodyByteBuf.readerIndex(), array, 0, readableLen);
                offset = 0;
            }

            //反序列化
            MessageLite result = messageLite.getParserForType().parseFrom(array, offset, readableLen);
            out.add(result);
        }
    }

    public static void main(String[] args) {
        System.out.println(BaseUtil.byteToHex((byte)15));
    }
}
